home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / perl / perlvisi.1 / perlvisi / perlvision / perlvision.doc < prev    next >
Encoding:
PGP Message  |  1995-03-22  |  23.0 KB  |  623 lines

  1. -----BEGIN PGP SIGNED MESSAGE-----
  2.  
  3. require 5.000;
  4.  
  5. # PerlVision - A class library to do ANSI graphics and textmode GUI
  6. # By Ashish Gulhati (hash@well.sf.ca.us)
  7. # V.0.1.0
  8. #
  9. # (C) Ashish Gulhati, 1995. All Rights Reserved.
  10. #
  11. # Free electronic distribution permitted. You are free to use
  12. # PerlVision in your own code so long as this copyright message stays
  13. # intact. PerlVision or derived code may not be used in any commercial
  14. # product without my prior written or PGP-signed consent. Please e-mail
  15. # me if you make significant changes, or just want to let me know what
  16. # you're using PerlVision for.
  17.  
  18.  
  19. INTRO
  20. =====
  21.  
  22. I needed a basic text-mode GUI framework to implement some
  23. nice-looking proggies on Linux. Didn't find any around, so necessity
  24. became the mother of PerlVision. And this beast kept growing as I made
  25. love to Perl, so now it's far from 'basic'. Provides 90% of the
  26. features you'd want for a user interface, including checkboxes,
  27. radiobuttons, three different styles (!) of pushbuttons, single and
  28. multiple selection listboxes, an extensible editbox that does
  29. autowrapping, a scrollable viewbox, single line text entry fields, a
  30. menubar with pulldown menus, and full popup dialog boxes with multiple
  31. controls, as well as optimization of screen updates to minimize
  32. transmission overhead on slow modem lines.
  33.  
  34. PerlVision is much more powerful and pretty than dialog, if I do say
  35. so myself. It is probably somewhat Linux specific, I haven't tried it
  36. on any other system, and it needs work to speed it up, which I'll get
  37. around to soon.
  38.  
  39. PerlVision will only work with Perl 5+ of-course (upgrade || die()!).
  40.  
  41.  
  42. MANIFEST
  43. ========
  44.  
  45. The perlvision.tgz file should contain:
  46.  
  47. pvbasic.pl    - Basic primitives for ANSI screen control, etc.
  48. pvbasic_u.pl    - 'Unoptimized' pvbasic.pl (faster on console)
  49. perlvision.pl    - The class library
  50. perlvision.doc    - This file
  51. rap        - (rap ain't pico) A simple text editor as an example
  52.                   of using PerlVision.
  53. COPYING        - The GPL - terms and conditions under which rap (but
  54.           not the rest of PerlVision) is distributed
  55. README        - General description of how to get started
  56. IAFA-PACKAGE    - The IETF FTP Archives Working Group standard format 
  57.                   description of PerlVision.
  58.  
  59. PerlVision is not public domain or copylefted software. You may make
  60. use of it for free as long as the resulting programs are not to be
  61. used for any commercial purpose. _Any_ commercial use of PerlVision
  62. requires my prior consent. If you aren't sure whether a certain use is
  63. 'commercial' on 'non-commercial', assume it is commercial and mail me.
  64.  
  65.  
  66. BASICS
  67. ======
  68.  
  69. Programs that use PerlVision should call pv::initvision() before doing
  70. any screen manipulation or creating any PerlVision objects. Before
  71. exiting, programs should call pv::exitvision() to set the terminal
  72. back to normal. pv::initvision() can be called with an argument that
  73. tells it whether or not to use IBM-PC high bit characters.
  74.  
  75. pv::initvision(1) sets it up to use high bit line drawing characters
  76. pv::initvision(0) sets it up to use makeshift 7 bit characters.
  77.  
  78. All proggies that use PerlVision should use the pv::pvprint() function
  79. instead of the standard print operator for terminal I/O, and use the
  80. attribute/cursor manipulation functions in pvbasic.pl rather than send
  81. the codes directly. This enables PerlVision to:
  82.  
  83. 1. keep track of the contents of the screen so that trashed screens
  84. can be restored and transient popup windows can restore what was under
  85. them when they vanish, and
  86.  
  87. 2. provide some amount of curses style optimization when updating the
  88. screen. While this optimization is currently rather inefficient and
  89. actually _slows_ the display on a terminal connected with a fast link
  90. (like the console), it does accomplish its primary function which is
  91. to keep the number of characters transmitted to a minimum for the
  92. benefit of folks using the proggy over a slow terminal line, like over
  93. a modem.
  94.  
  95. pv::pvprint() is behaves almost identically to print() except it don't
  96. like multiple line input (it'll strip everything after the first
  97. newline), and it don't like you to use terminal control escape codes
  98. (it won't complain about this, but you'll be defeating the whole
  99. purpose if you do it).
  100.  
  101. So to flush the virtual screen built up by the use of pvprint() calls,
  102. you use pv::refresh(); There's also a pv::redraw() to completely
  103. redraw the whole screen (useful if screen is trashed - I normally have
  104. all the controls do this if they receive a ^L keystroke).
  105.  
  106. Finally, pv::standard sets up a standard screen for you to use. I
  107. wrote PerlVision to serve as an interface for a much larger project,
  108. and that's what I wanted all my screens to look like, so that's what's
  109. standard. If you decide to go with a different look, the controls
  110. should still work just fine, but since colors are hardcoded
  111. everywhere, it might look funny without a cyan background. Ideally
  112. somebody will hack around and fix up PerlVision to use a color table
  113. for attributes of all the controls, but it ain't gonna be me. ;)
  114.  
  115. The same goes with keystrokes. Package pv has a function called
  116. getkey() which is used for most keyboard input as it does some
  117. interpretation before submitting the result. I use emacs-like meta
  118. sequences for things like Help and Main Menu activation, so M-h and
  119. M-x are defined for that and will exit any control that has focus. If
  120. you want to change that, well, you have the source.
  121.  
  122. Look in pvbasic.pl or in the source for rap to see what functions to
  123. use to set cursor position, colors, etc. It's all mostly
  124. self-explanatory. Any function that uses terminal capabilities that
  125. give it extra speed (cls, cleol, hardware scrolling) DON'T wait for a
  126. refresh() call, but so their deeds right away. That's because
  127. refresh() isn't smart enough to optimize to that great an extent, and
  128. it would be horrid to have it put out 24x80 chars everytime you did a
  129. cls(). These functions still do update the internally stored status of
  130. the screen, of-course.
  131.  
  132.  
  133. CLASSES
  134. =======
  135.  
  136. The following object classes are defined:
  137.  
  138. PV_Static    (A static text region, trivial class)
  139. PV_Checkbox     (A single 2-state checkbox)
  140. PV_Radio    (A single 2-state radiobutton)
  141. PV_RadioG    (A group of connected radiobuttons)
  142. PV_Listbox    (A single selection list box)
  143. PV_Mlistbox    (A multiple selection list box)
  144. PV_Entryfield    (A single line text entry field)
  145. PV_Password    (A single line text entry field that *'s out what's typed)
  146. PV_Menubar    (A top line menu bar with single-level pulldown submenus)
  147. PV_Combobox    (A combo box)
  148. PV_Editbox    (A multi line edit box)
  149. PV_Viewbox    (A readonly viewer/pager for text files)
  150. PV_Pushbutton    (A push button that takes 3 lines of screen real estate)
  151. PV_Cutebutton    (A push button that takes 2 lines of screen real estate)
  152. PV_Plainbutton  (A no-frills button that fits on a single line)
  153. PV_Dialog    (A full dialog box with as many controls as you like)
  154.  
  155. * Other classes are defined for internal use by PerlVision and should
  156.   not be used from outside. Also, see below why use of the PV_Radio
  157.   control is limited from outside.
  158.  
  159. * Constructors for all the classes are called new().
  160.  
  161. * All classes expect that you will not fiddle with the object's data
  162.   yourself.
  163.  
  164. * All nontrivial controls (except PV_RadioG, see below) have an
  165.   activate() method. It makes the control active, and returns when any
  166.   traditional shift focus key is pressed - see the section on
  167.   PV_Dialog for more details.
  168.  
  169. * All nontrivial controls have a stat() method, which returns the
  170.   status of the control (checked, unchecked, text, whatever).
  171.  
  172.  
  173. I. PV_Static
  174. ============
  175.  
  176. $foo = new PV_Static ("Text",$x1,$y1,$x2,$y2);
  177.  
  178. This is the trivial text region control. It's there mainly so you can
  179. put static text in dialog boxes. It don't have a activate() or stat()
  180. method.
  181.  
  182. $foo->display;
  183.  
  184. to display the text. If your text doesn't fit in the space you
  185. allocate, it'll be truncated. It's also your responsibility to provide
  186. line breaks if you don't want all the text to be thought of as a
  187. single line.
  188.  
  189.  
  190. II. PV_Checkbox
  191. ===============
  192.  
  193. $foo = new PV_Checkbox ("Label",$x,$y,$stat);
  194.  
  195. $x,$y are the X and Y co-ordinates to place the control.
  196. $stat is 1 if the Checkbox is checked, 0 if not. You can pre-initialize.
  197. "Label" is printed on the left of the checkbox.
  198.  
  199. $foo->display;         Displays checkbox.
  200. $foo->activate;        Gives it focus. Exits on 1,2,3,4,5,6,7 codes.
  201. $foo->select;        Toggles status.
  202. $foo->stat;        Returns status. (1 checked, 0 unchecked)
  203.  
  204.  
  205. III. PV_Radio
  206. =============
  207.  
  208. $foo = new PV_Radio ("Label",$x,$y,$stat);
  209.  
  210. PV_Radio is a direct descendant of PV_Checkbox that just looks a bit
  211. different. All the methods defined for PV_Checkbox are defined for
  212. PV_Radio as well, BUT don't try to use PV_Radio as a different looking
  213. PV_Checkbox.
  214.  
  215. Because radio buttons are generally meant to be grouped and to affect
  216. the state of all other buttons in the group. So unless you include a
  217. radio button in a group with PV_RadioG (see below), you're liable to
  218. hurt something. Once it's in a group you can use all the methods
  219. outlined above for PV_Checkbox.
  220.  
  221.  
  222. IV. PV_RadioG
  223. =============
  224.  
  225. $foo = new PV_RadioG ($radio_1,$radio_2,$radio_3...);
  226.  
  227. $radio_* are PV_Radio objects.
  228.  
  229. See? You take your PV_Radio objects, and feed them to the constructor
  230. for PV_RadioG, and out pops a radio button group.
  231.  
  232. Now you can use:
  233.  
  234. $foo->display;         Displays all radio buttons in group.
  235. $foo->stat;        To figure out which button is the one that's
  236.             selected. This returns the Label of the selected
  237.             button.
  238.  
  239. PV_RadioG has no 'activate' method. You activate the PV_Radio objects
  240. directly. This is much more flexible for use in dialog boxes.
  241.  
  242.  
  243. V. PV_Listbox
  244. =============
  245.  
  246. $foo = new PV_Listbox ("Head",$x1,$y1,$x2,$y2,"Label1",0,"Label2",0...);
  247.  
  248. Yes, the element following each "Labeln" should be 0 for this to work
  249. right.
  250.  
  251. "Label*" are the strings that will be shown in the listbox. "Head"
  252. will be printed across above the top of the listbox.
  253.  
  254. $foo->activate;        Gives it focus. Exits on 5,6,7,8 exit codes.
  255. $foo->stat;        Returns the label of the selected entry.
  256.  
  257.             
  258. VI. PV_Mlistbox
  259. ===============
  260.  
  261. $foo = new PV_Mlistbox ("Head",$x1,$y1,$x2,$y2,"Label1",0,"Label2",0...);
  262.  
  263. Yes, the element following each "Labeln" should be 0 for this to work
  264. right.
  265.  
  266. "Label*" are the strings that will be shown in the listbox. "Head"
  267. will be printed across above the top of the listbox.
  268.  
  269. $foo->activate;        Gives it focus. Exits on 5,6,7,8 exit codes.
  270. $foo->stat;        Returns a list of all selected labels.
  271.  
  272.  
  273. VII. PV_Entryfield
  274. ==================
  275.  
  276. $foo = new PV_Entryfield ($x,$y,$length,$max,"Label","Initial Value");
  277.  
  278. $length is the length of the text entry area.
  279. $max is the maximum length of the input. actually this is ignored. ;-)
  280. "Label" is printed to the left of the entry field. Can be "".
  281. The entryfield is pre-initialized to "Initial Value". Can be "".
  282.  
  283. $foo->activate;        Gives it focus. Exits on 1,2,5,6,7,8 exit codes.
  284.             Changed text is always saved, regardless of
  285.             how the loop exited.
  286. $foo->stat;        Returns the text value of the entryfield.
  287.  
  288.  
  289. VIII. PV_Password
  290. =================
  291.  
  292. Identical to PV_Entryfield except that it displays '*'s instead of
  293. what the user types.
  294.  
  295.  
  296. IX. PV_Menubar
  297. ==============
  298.  
  299. The menu bar is a bit odd. The way you do it is set it up with just
  300. one pulldown, then add pulldowns to it till you have enough. Don't add
  301. too many (i.e. that there's not enough space for their heads on the
  302. menubar) or things will definitely get broken.
  303.  
  304. $foo = new PV_Menubar ("Head",$width,$depth,"label1",0,"label2",0...);
  305.  
  306. Just like with the listboxes, each list element is followed by a
  307. 0. This list becomes your first pulldown. Now to add more pulldowns, do:
  308.  
  309. $foo->add("Head",$width,$depth,"label1",0,"label2",0...);
  310.  
  311. That's the second pulldown, and so on.
  312.  
  313. Because of this step by step method of building up the menubar, you
  314. need to display it once you're finished adding pulldowns, it doesn't
  315. automatically display itself. Do a:
  316.  
  317. $foo->display();
  318.  
  319. To activate:
  320.  
  321. $foo->activate();
  322.  
  323. It'll exit on 5, 7, and 8. On 8, it'll give you a second element in
  324. the return list of the form "Pulldown:Selection". The "Pulldown" is
  325. the head of the pulldown menu, the "Selection" is the label of the
  326. selection.
  327.  
  328. Help context does not come through on the 5 exit code. i.e. you can't
  329. tell which pulldown was active when help was requested, or which
  330. selection in which pulldown. C'est la vie.
  331.  
  332.  
  333. X. PV_Combobox
  334. ==============
  335.  
  336. Not implemented yet. I'll get around to it. Actually it's a pretty
  337. trivial offspring of a listbox and an entryfield.
  338.  
  339.  
  340. XII. PV_Editbox
  341. ===============
  342.  
  343. $foo = new PV_Editbox ($x1,$y1,$x2,$y2,$margin,"Text",$index,$start);
  344.  
  345. $margin is the word-wrap boundary. If it's bigger than the size of the
  346. box, that's your headache.
  347.  
  348. $text is a text string to be dumped into the editbox. it will be
  349. stripped of CRs (not LFs), TABs, and nulls, and justified the way the
  350. editbox does it (see below).
  351.  
  352. $index is the start position within the text to initially place the
  353. cursor at. First char is 0.
  354.  
  355. $start is the line number to position at the top of the editbox, if
  356. possible. First line is 0.
  357.  
  358. $foo->activate;        Gives it focus. Exits on 5,6,7 exit codes.
  359.             Changed text is always saved, regardless of
  360.             how the loop exited.
  361. $foo->stat;        Returns the text value of the editbox.
  362.  
  363. There are some hooks in there to let you subclass it and do
  364. things. One is an empty 'sub statusbar' that's called every-time the
  365. display is refreshed. Another is an empty 'sub process_key' which is
  366. used extensively in rap to build a full editor out of the editbox
  367. control.
  368.  
  369. The editbox does automatic word-wrapping and reverse word-wrapping and
  370. other fancy stuff. The style of auto-wrapping I chose is what
  371. personally irritates me the least (all auto-wraps irritate me). Trying
  372. to change the wrap style is likely to be very hairy, and will prolly
  373. break the editbox. It took a lot of tweaking of plenty of regexps to
  374. get it to work the way it does.
  375.  
  376. The editbox used to scale quite poorly with increasing text sizes
  377. initially, but I've cleaned it up so there's only one or two places
  378. where the size of the input text matters at all to the
  379. speed. Basically it should now be more or less constant efficiency
  380. most of the time, except when an auto-wrap occurs, at which time, the
  381. size of the text makes a significant difference. I'll make that
  382. size-independent as well in the next version.
  383.  
  384.  
  385. XIII. PV_Viewbox
  386. ================
  387.  
  388. $foo = new PV_Viewbox ($x1,$y1,$x2,$y2,$text,$start);
  389.  
  390. Much like PV_Editbox but it's readonly and the arrow keys have
  391. different bindings. I will eventually implement hardware scrolling in
  392. viewboxes that extend the length of the display so that it's a fast
  393. browser.
  394.  
  395.  
  396. XIV. PV_Pushbutton, PV_Cutebutton, PV_Plainbutton
  397. =================================================
  398.  
  399. $foo = new PV_Pushbutton ("Label",$x1,$y1);
  400.  
  401. Makes a simple push button.
  402.  
  403. $foo->display(); displays it.
  404.  
  405. $foo->activate(); activates it.
  406.  
  407. Exits on codes 1,2,3,4,5,6,7,8. On 8, it 'depresses' and it's up to
  408. you to 'undepress' it by calling the display method.
  409.  
  410. PV_Pushbutton is BIG. It takes 3 lines on the screen. PV_Cutebutton is
  411. my favorite - it takes only two lines, and actually pushes and pops
  412. around so it's fun to watch ;) PV_Plainbutton is a basic one-line
  413. button which does absolutely nothing fancy but is very useful in some
  414. situations (e.g. for hyper-text).
  415.  
  416.  
  417. XV. PV_Dialog
  418. =============
  419.  
  420. This is the guy that puts it all together and does all the work of
  421. managing how focus switches between multiple controls in a dialog
  422. box. Once you've created all the controls you need, you can feed them
  423. to PV_Dialog and out pops an object that you can trust to handle
  424. everything. Above you would have noticed that the activate loops for
  425. all controls return en exit code when focus is released. This is what
  426. these codes mean:
  427.  
  428. When an activate loop exits, it returns a code telling you the reason
  429. for exiting:
  430.  
  431. 1 = Up Arrow        (Traditional shift-focus key)
  432. 2 = Down Arrow        (Traditional shift-focus key)
  433. 3 = Right Arrow        (Traditional shift-focus key)
  434. 4 = Left Arrow        (Traditional shift-focus key)
  435. 5 = M-h          (For  help)
  436. 6 = M-x         (For menu)
  437. 7 = Tab         (Traditional shift-focus key)
  438. 8 = Enter        (Traditional 'Done here' key)
  439.  
  440. These codes are used by the PV_Dialog control to figure out how to
  441. switch focus between controls, and when to exit. Here's how to create
  442. a PV_Dialog object:
  443.  
  444. $foo = new PV_Dialog ("Title",$x1,$y1,$x2,$y2,$style,$color,
  445.               $control1,1,2,2,1,1,1,2,0,
  446.               $control2,1,3,3,1,2,2,3,0,
  447.               ...);
  448.  
  449. "Title" is currently ignored.
  450. $style: if 1, creates a popup that is 'raised'.
  451.         if 0, creates a popup that is 'depressed'
  452. $color is the background color for the dialog. I'd recommend 6 (cyan)
  453.        because of the overall hardcoded buddha-nature of colors at
  454.        present.
  455.  
  456. $control* are PV_* objects that you created beforehand (I think they
  457. can even be PV_Dialog types, though I haven't tested it. They can't be
  458. PV_Menubar types of-course).
  459.  
  460. How this works is that the matrix tells PV_Dialog which control to
  461. switch focus to on each og the 8 exit codes listed above. So when you
  462. do a:
  463.  
  464. $foo->activate;
  465.  
  466. PV_Dialog starts off by displaying itself and giving focus to
  467. $control1. When $control1 exits, $foo looks in the list that follows
  468. $control1 in the constructor syntax above to figure out which control
  469. to give focus to next. The list is simply numbers that say which
  470. control. So 1 represents $control1, 2 represents $control2, and so on,
  471. strictly based on the order in which the controls appear in the
  472. constructor invocation.
  473.  
  474. The special value 0 is reserved to tell PV_Dialog that it's time to
  475. exit and hide the dialog box. I also use it as a place-holder for
  476. those exit-codes that a certain control never returns, for example of
  477. $control1 above was a PV_Editbox, I'd put 0's in the list following
  478. $control1 at positions 1,2,3 and 4 because the edit box object never
  479. exits on those codes (those keys have meaning within the editbox)
  480.  
  481. If you don't want focus to switch off a control when a certain
  482. exitcode is returned, simply put that control's own number in the
  483. corresponding position in the list.
  484.  
  485. Look in the rap code for an example of PV_Dialog use, the $options
  486. object. It's generally very easy and powerful.
  487.  
  488. When PV_Dialog's activate exits, it returns a two-element list. First
  489. element tells you which was the last control to be active (again
  490. numbered as they appear in the constructor invocation), and the second
  491. element tells you what exitcode that control returned.
  492.  
  493. After the dialog box has exited, you can call 'stat' on each control
  494. to find out what's up. Remember, don't put PV_RadioG controls in a
  495. dialog box, they don't have an activate method. Put the corresponding
  496. PV_Radio controls in. When you 'stat', you'll be 'stat'ing the
  497. PV_RadioG.
  498.  
  499. Also, don't ever put a PV_Static as the first control in a
  500. PV_Dialog. It doesn't have an activate method. If you just want a
  501. pop-up box with text and no other controls, either consider using a
  502. PV_Viewbox control, or write the text onto the popup box yourself with
  503. pv::pvprint.
  504.  
  505.  
  506. More goodies: PVD
  507. =================
  508.  
  509. PerlVision also defines two often needed dialog box styles:
  510.  
  511. PVD::message    (A simple message box with OK button)
  512. PVD::yesno    (An option box with Yes/No buttons)
  513.  
  514. Both self-center, and make sure the box is big enough to hold the
  515. buttons. They don't bother to check if the screen will hold the dialog
  516. box, or the dialog box will hold your text. Both use the following
  517. syntax:
  518.  
  519. PVD::message ("Text",width,depth);
  520.  
  521. PVD::yesno returns 1 for yes and 0 for no.
  522.  
  523. Width and depth are how big you want the text part of the box to be
  524. (the buttons are separate).
  525.  
  526.  
  527. BUGS
  528. ====
  529.  
  530. * ORA don't have a distributor in India, so I don't own a camel.
  531. * $max in PV_Entryfield is a misnomer. It's actually used internally
  532.   and should be set to 0 when you create a new entryfield object.
  533. * Colors are hardcoded.
  534. * Terminal control sequences are hardcoded.
  535. * Keystroke sequences are hardcoded.
  536. * No support for multiple overlapping 'windows'.
  537. * The virtual screen 'optimization' code could do with a few orders of
  538.   magnitude increase in performance. I'll rewrite it as a C module
  539.   when I figure out how that's done. Or using ncurses if I figure out
  540.   how to access ncurses from Perl. Assistance welcome.
  541. * Why do people use text mode if they want GUI controls?
  542.  
  543.  
  544. CRUFTS
  545. ======
  546.  
  547. * I've included pvbasic_u.pl with the distribution for now. This is
  548. basically an old version of the pvbasic.pl _without_ the
  549. screen-optimization code, hacked up with the new version in places so
  550. that it does at least keep a track on the status of the screen
  551. (without which PerlVision's transient window support would break). The
  552. idea is that until I get around to coding the screen optimization code
  553. in C, folks can use pvbasic_u.pl on fast terminals. It's substantially
  554. faster on console than the real pvbasic.pl. Hopefully I'll soon have
  555. an ncurses-based pvbasic.pl done, which will be much faster than
  556. either of these two.
  557.  
  558.  
  559. TO DO
  560. =====
  561.  
  562. * PV_Combobox
  563. * Hardware scrolling for listboxes, viewboxes and editboxes that
  564.   extend the width of the screen.
  565. * Speed up screen optimization
  566. * Make screen updating 'interruptible' so that if you know what you're
  567.   doing, you needn't wait till the update is done - much like the
  568.   'type-ahead' mode in BBS packages. Suggestions on how to implement
  569.   this are welcome.
  570. * Implement hot-keys in menubar and pulldowns.
  571. * Use termcap || terminfo for terminal characteristics. Preferably
  572.   ncurses as that'll take care of the screen optimization problem as well.
  573. * Make listboxes more extensible
  574. * Add quoting support to editbox's justify routine
  575. * Make syntax identical to Tk eventually, so the same code can be made
  576.   X capable with a minimum of fuss.
  577. * Make auto-fill optional in editbox and fix tab handling so that rap
  578.   can also be used to edit /etc/hosts instead of just mail ;-/
  579. * Implement keymap objects. pv::getkey is just an excuse for an input
  580.   model.
  581.  
  582. IF YOU KNOW OF A WORKING XS INTERFACE FOR LINKING PERL WITH NCURSES,
  583. or have the skills and the time to help make it, please e-mail me. All
  584. other offers of help with future versions of PerlVision, suggestions
  585. for improvement, as well as news on what you're using PerlVision for
  586. are welcome.
  587.  
  588. Enjoy!
  589.  
  590.  
  591. THANKS TO
  592. =========
  593.  
  594. Raj, my Unix mentor. Kishore for being such a nice guy and blunt
  595. freak. Anindo for suggestions, cigarettes, and hair-raising bike
  596. rides. Steve for encouragement and eats. Uma for not distracting me
  597. with her lovely kisses for a while. Atul, Rishab and Pawan for
  598. existing. Mohua for company. Emily Saliers and Neil Peart for
  599. fantastic music. Larry Wall for Perl. RMS for Emacs.
  600.  
  601.  
  602. ============================================================================
  603.                                         __
  604.     -----==-                           / /\       Ashish Guhati
  605.     ----==-- _                        / /  \      hash@netropolis.com
  606.     ---==---(_)__  __ ____  __       / / /\ \     hash@well.sf.ca.us
  607.     --==---/ / _ \/ // /\ \/ /      / /_/\ \ \    Vox:     +91 11 4615433
  608.     -=====/_/_//_/\_,_/ /_/\_\     /______\ \ \   BBS/FAX: +91 11 4601978
  609.   The choice of a GNU generation   \_________\/   http://c2.org/~hash/
  610.  
  611.               Finger hash@well.sf.ca.us for PGP public key.
  612. ============================================================================
  613.  
  614. -----BEGIN PGP SIGNATURE-----
  615. Version: 2.6.2
  616.  
  617. iQCVAwUBL3CUWGXU8SuBC/ZVAQG4GAQAgjSD1zZdmdFUsOzjJ2xTSEAmmknBemb9
  618. uKZ+LET7gPm6gZ3xPQrOqGKz2Lp8uvOjDd0hMSAZYP4nZDG5z46rqbBAbA5eMoGQ
  619. whwC8rbAabiGdoMdmR1hlMnFSM8tarCOQHn/RGneVSBVW4DEM/sYyIchVHWgzgTH
  620. IZTHIy9j8Ho=
  621. =6Dq1
  622. -----END PGP SIGNATURE-----
  623.